package nl.jjsoft.airlock.view.presenters
{
	import flash.events.Event;
	import flash.events.IEventDispatcher;
	
	import mx.core.UIComponent;
	import mx.events.FlexEvent;
	import mx.logging.ILogger;
	import mx.logging.Log;
	
	import nl.jjsoft.airlock.view.Settings;
	
	public class AbstractPresenter implements IPresenter
	{
		private static const logger:ILogger = Log.getLogger("AbstractPresenter");
		
		public var isViewCreationComplete:Boolean = false;
		
		/**
		* The view class we're injecting into the view mediator.
		*/
		protected var viewType:Class;
		
		protected var _view:UIComponent;
		
		[Dispatcher]
		/**
		 * The [Dispatcher] metadata tag instructs Swiz to inject an event dispatcher.
		 * Event's dispatched via this dispatcher can trigger event mediators.
		 */ 
		public var dispatcher : IEventDispatcher;
		
		public function AbstractPresenter(viewType:Class=null) {
			super();
			logger.debug("Constructor");
			this.viewType = viewType;
		}
		
		/**
		* Listen for views added to the stage and determine if it's the corresponding
		* View for this View Mediator. This check is done by looking at the view added
		* to the stage and do a simple compare on the <code>viewType:Class</code> class
		* member that we set in concrete View Medators via their constructors.
		*
		* <p>
		* Also determine if the View has fired its creation complete event so developers
		* can perform actions on the view from the View Mediator without hitting null pointers
		* for uninstantiated objects in the View. If the creation complete has not fired, then
		* listen for it.
		* </p>
		*/
		[Mediate( "flash.events.Event.ADDED_TO_STAGE", properties="target", useCapture="true" )]
		public function setView(value:*):void {
			if(viewType != null && value is viewType) {
				logger.debug("AUTOWIRE :: view = " + value);
				this._view = value;
				// determine if the view has been initialized...
				// NO...listen for it;s creation complete event
				if(this._view.initialized == false) {
					this._view.addEventListener(FlexEvent.CREATION_COMPLETE, onCreationComplete);
				} else {
					// YES...call the init() method to kick off the instation of the view mediator
					this.isViewCreationComplete = true;
					this.init();
				}
				// don't get in GC's way if the view is removed
				this._view.addEventListener(Event.REMOVED_FROM_STAGE, cleanup);
			}
			else
			{
			//              logger.warn("Don't inject the view " + value);
			}
		}

		protected function init():void {
			logger.debug("init");
			this.setViewListeners();
		}
		
		protected function setViewListeners():void {
			logger.debug("setViewListeners");
			// OVERRIDDEN
		}
		
		protected function onCreationComplete( event:FlexEvent ):void {
			logger.debug("onCreationComplete");
			this.isViewCreationComplete = true;
			this._view.removeEventListener(FlexEvent.CREATION_COMPLETE, onCreationComplete);
			this.init();
		}
 
 		protected function cleanup( event:Event ):void {
			logger.debug("cleanup");
			this._view.removeEventListener(Event.REMOVED_FROM_STAGE, cleanup);
		}
		
		/**
		 * Convenience method which concrete implementations of the AbstractPresenter can use
		 * to add event listeners to components.
		 * @param target The target component for which the event handler is registered, for example a Button.
		 * @param eventType The event to register the event handler for, for example MouseEvent.CLICK.
		 * @param method The listener which is called when the target dispatches the event of type eventType.
		 * @param <p>passEventAsParamToListener When true, the first parameter of the event listener is the event that is dispatched. 
		 * When false, the event listener does not expect a parameter of the event type.</p>
		 * @param params The params that must be passed to the event listener. If passEventAsParamToListener is true, the first parameter
		 * is the event type.
		 */
		protected function registerEventHandler(target:UIComponent, eventType:String, method:Function, passEventAsParamToListener:Boolean=false, params:Array=null):void {
			if (params == null) {
				if (passEventAsParamToListener) {
					target.addEventListener(eventType, function(event:Event):void {method.call(null, event);});
				} else {
					target.addEventListener(eventType, function(event:Event):void {method();});
				}
			} else {
				target.addEventListener(eventType, function(event:Event):void {
					var p:Array = new Array(params);
					if (passEventAsParamToListener) {
						p.unshift(event);
					}
					method.apply(null, p);
				});
			}
		}
	}
}